﻿#include <iostream>
#include "Win32Utils/CDeviceHelper.h"
#include "Win32Utils/CWmiQueryHelper.h"
#include "Win32Utils/CStrUtils.h"
#include "CPerformHelper.h"

int main()
{
    setlocale(LC_ALL, "");

    std::vector<VIDEO_ADAPTER_DESC_INFO> vResult = CDeviceHelper::GetAllVideoAdapterDesc();

    CDeviceHelper obj;
    obj.Initialize();

    clock_t tmBegin = ::clock();
    DEVICE_INFO info = obj.GetDeviceInfo();
    clock_t tmEnd = ::clock();


    DEVICE_VIDEO_CONTROLLER_INFO gpuInfo;

    for (int i = 0; i < 100; i++)
    {
        vResult = CDeviceHelper::GetAllVideoAdapterDesc();
    }

    CStrUtils::ConsolePrintf(_T("cost time: %d\r\n"), tmEnd - tmBegin);

    CPerformHelper perfmon;

    int nTimeInterval = 1000;

    perfmon.Initialize();
    perfmon.SetCollectInterval(nTimeInterval);
    perfmon.AddCounter(_T(PERFM_PATH_CPU_UTILITY));
    perfmon.AddCounter(_T(PERFM_PATH_DISK_READ_RATE));
    perfmon.AddCounter(_T(PERFM_PATH_DISK_WRITE_RATE));
    perfmon.AddCounter(_T(PERFM_PATH_CPU_PERFORMANCE));
    perfmon.AddCounter(_T(PERFM_PATH_CPU_FREQUENCY));
    perfmon.AddCounter(_T(PERFM_PATH_NETWORK_RECV_RATE));
    perfmon.AddCounter(_T(PERFM_PATH_NETWORK_SENT_RATE));
    perfmon.AddCounter(_T(PERFM_PATH_GPU_UTILITY));
    perfmon.AddCounter(_T(PERFM_PATH_GPU_MEMORY_DEDICATED_USAGE_UTILITY));
    perfmon.AddCounter(_T(PERFM_PATH_GPU_MEMORY_SHARE_USAGE_UTILITY));
    perfmon.AddCounter(_T(PERFM_PATH_GPU_MEMORY_TOTAL_COMMITTED_USAGE_UTILITY));
    perfmon.AddCounter(_T(PERFM_PATH_PROCESS_V2_PROCESSOR_TIME));
    perfmon.AddCounter(_T(PERFM_PATH_PROCESS_V2_USER_TIME));
    perfmon.StartCollect();

    PDH_FMT_COUNTERVALUE value = { 0 };

    SIZE_T DedicatedVideoMemory = vResult[0].AdapterDesc.DedicatedVideoMemory;
    SIZE_T DedicatedSystemMemory = vResult[0].AdapterDesc.DedicatedSystemMemory;
    SIZE_T SharedSystemMemory = vResult[0].AdapterDesc.SharedSystemMemory;

    MEMORYSTATUSEX memStatus = { 0 };
    memStatus.dwLength = sizeof(MEMORYSTATUSEX);

    double lfFrequency = 0.0f;
    while (true)
    {
        ::GlobalMemoryStatusEx(&memStatus);
        CStrUtils::ConsoleSetPos(0, 0);
        CStrUtils::ConsoleClear();

        //获取CPU占用率
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_CPU_UTILITY), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("CPU 利用率: %.2lf%% "), value.doubleValue);
            //CStrUtils::ConsolePrintf(_T("\r\n"));
        }

        //获取CPU性能
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_CPU_FREQUENCY), PDH_FMT_DOUBLE, &value))
        {
            lfFrequency = value.doubleValue;
        }

        //获取CPU性能
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_CPU_PERFORMANCE), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("当前主频: %.2lf Ghz "), value.doubleValue / 100.0f * lfFrequency / 1000.0f);
            CStrUtils::ConsolePrintf(_T("基准频率: %.2lf Ghz"), lfFrequency / 1000.0f);
            CStrUtils::ConsolePrintf(_T("\r\n"));
        }

        //物理内存
        CStrUtils::ConsolePrintf(_T("内存: %.1lf"), CStrUtils::FormatByteSize(memStatus.ullTotalPhys - memStatus.ullAvailPhys, CStrUtils::eUnitType::eUT_B, CStrUtils::eUnitType::eUT_GB).value);
        CStrUtils::ConsolePrintf(_T("/"));
        CStrUtils::ConsolePrintf(_T("%s "), CStrUtils::FormatByteSize(memStatus.ullTotalPhys, CStrUtils::eUnitType::eUT_B, CStrUtils::eUnitType::eUT_GB).strOutput.c_str());
        CStrUtils::ConsolePrintf(_T("%.2lf%%"), (double)(memStatus.ullTotalPhys - memStatus.ullAvailPhys) * 100 /(double)memStatus.ullTotalPhys);
        CStrUtils::ConsolePrintf(_T("\r\n"));

        //获取进程处理器时间
        PDH_VALUE_LIST ProcessorTimeList = perfmon.GetFormattedCounterArray(_T(PERFM_PATH_PROCESS_V2_PROCESSOR_TIME), PDH_FMT_DOUBLE);

        //获取进程用户时间
        PDH_VALUE_LIST UserTimeList = perfmon.GetFormattedCounterArray(_T(PERFM_PATH_PROCESS_V2_USER_TIME), PDH_FMT_DOUBLE);

        auto itFindProcessor = ProcessorTimeList.find(_T("cpuz:2972"));
        auto itFindUser = UserTimeList.find(_T("cpuz:2972"));
        if (itFindProcessor != ProcessorTimeList.end())
        {
            CStrUtils::ConsolePrintf(_T("处理器时间 %s: %lf\r\n"), itFindProcessor->first.c_str(), itFindProcessor->second.doubleValue / 6.0f);
        }

        if (itFindUser != UserTimeList.end())
        {
            CStrUtils::ConsolePrintf(_T("用户时间 %s: %lf\r\n"), itFindUser->first.c_str(), itFindUser->second.doubleValue / 6.0f);
        }

        //获取GPU占用率
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_GPU_UTILITY), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("GPU 利用率: %.1lf%%"), value.doubleValue);
            CStrUtils::ConsolePrintf(_T("\r\n"));
        }

        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_GPU_MEMORY_DEDICATED_USAGE_UTILITY), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("专用 GPU 内存: %0.1lf"), CStrUtils::FormatByteSize(value.doubleValue, CStrUtils::eUnitType::eUT_B, CStrUtils::eUnitType::eUT_GB).value);
            CStrUtils::ConsolePrintf(_T("/%s"), CStrUtils::FormatByteSize(DedicatedVideoMemory).strOutput.c_str());
            CStrUtils::ConsolePrintf(_T("\r\n"));
        }

        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_GPU_MEMORY_SHARE_USAGE_UTILITY), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("共享 GPU 内存: %0.1lf"), CStrUtils::FormatByteSize(value.doubleValue, CStrUtils::eUnitType::eUT_B, CStrUtils::eUnitType::eUT_GB).value);
            CStrUtils::ConsolePrintf(_T("/%s"), CStrUtils::FormatByteSize(SharedSystemMemory).strOutput.c_str());
            CStrUtils::ConsolePrintf(_T("\r\n"));
        }

        //获取硬盘读速度
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_DISK_READ_RATE), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("磁盘 读取: %s/s "), CStrUtils::FormatByteSize(value.doubleValue).strOutput.c_str());
        }

        //获取硬盘写速度
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_DISK_WRITE_RATE), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("磁盘 写入: %s/s"), CStrUtils::FormatByteSize(value.doubleValue).strOutput.c_str());
            CStrUtils::ConsolePrintf(_T("\r\n"));
        }

        //获取网络读速度
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_NETWORK_RECV_RATE), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("网络 接收: %sps "), CStrUtils::FormatByteSize(value.doubleValue).strOutput.c_str());
        }

        //获取网络写速度
        if (perfmon.GetFormattedCounterArray(_T(PERFM_PATH_NETWORK_SENT_RATE), PDH_FMT_DOUBLE, &value))
        {
            CStrUtils::ConsolePrintf(_T("网络 发送: %sps"), CStrUtils::FormatByteSize(value.doubleValue).strOutput.c_str());
            CStrUtils::ConsolePrintf(_T("\r\n"));
        }

        CStrUtils::ConsolePrintf(_T("\r\n"));
        ::Sleep(nTimeInterval);
    }

    return 0;
}
